package cn.zebra.dev.admin.module.admin.service.impl;

import cn.zebra.dev.admin.module.admin.dao.AdminDao;
import cn.zebra.dev.admin.module.admin.entity.AdminEntity;
import cn.zebra.dev.admin.module.admin.entity.AdminRoleItemEntity;
import cn.zebra.dev.admin.module.admin.service.AdminRoleItemService;
import cn.zebra.dev.admin.module.admin.service.AdminService;
import cn.zebra.dev.common.utils.SecurityUtils;
import cn.zebra.dev.common.utils.StrUtils;
import cn.zebra.dev.ibatis.plus.service.impl.ServiceImpl;
import cn.zebra.dev.ibatis.plus.utils.PageUtils;
import cn.zebra.dev.ibatis.plus.utils.Query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 后台用户
 *
 * @author runnable
 * @date 2019-09-07 16:00:10
 */
@Service
public class AdminServiceImpl extends ServiceImpl<AdminDao, AdminEntity> implements AdminService {

    @Autowired
    private AdminRoleItemService roleItemService;

    @Override
    public PageUtils<AdminEntity> findPage(Map<String, Object> params) {
        QueryWrapper<AdminEntity> wrapper = new QueryWrapper<>();
        wrapper.apply(params.containsKey("createId"), "create_id = {0}", params.get("createId"));
        wrapper.apply(params.containsKey("userName"), "admin_name LIKE CONCAT('%', {0}, '%')", params.get("userName"));
        IPage<AdminEntity> iPage = this.page(
                new Query<AdminEntity>(params).getPage(),
                wrapper
        );
        return new PageUtils<>(iPage);
    }

    @Override
    public AdminEntity findAdminByAccount(String account) {
        AdminEntity entity = this.findByFieldValue(AdminEntity::getAccount, account);
        List<Long> roleIds = roleItemService.findRoleIdListByAdminId(entity.getId());
        entity.setRoleIds(roleIds);
        return entity;
    }

    @Override
    public Boolean resetPassword(Long adminId, String salt, String password) {
        AdminEntity admin = new AdminEntity();
        Long lastLoginTime = System.currentTimeMillis();
        admin.setLastLoginTime(lastLoginTime);
        admin.setPassword(SecurityUtils.getMd5(salt + lastLoginTime + password));
        return update(admin, "id = {0}", adminId);
    }

    @Override
    public AdminEntity findById(Long id) {
        AdminEntity entity = super.findById(id);
        List<Long> ids = roleItemService.findRoleIdListByAdminId(id);
        entity.setRoleIds(ids);
        return entity;
    }

    @Override
    public void saveAdmin(AdminEntity entity, Long createId) {
        entity.setCreateId(createId);
        entity.setCreateTime(LocalDateTime.now());
        if (StrUtils.isBlank(entity.getSalt())) {
            entity.setSalt(SecurityUtils.getMd5(StrUtils.getUUID()));
        }
        entity.setLastLoginIp("");
        entity.setLastLoginTime(0L);
        entity.setPassword(SecurityUtils.getMd5(entity.getSalt() + entity.getLastLoginTime() + entity.getPassword()));
        if (!save(entity)) {
            throw new RuntimeException("保存管理员失败!");
        }
        Collection<Long> roleIds = entity.getRoleIds();
        saveRoles(entity.getId(), roleIds);
    }

    @Override
    public void saveAdminAndRole(AdminEntity entity, Long createId) {
        if (this.findAdminByAccount(entity.getAccount()) != null) {
            throw new RuntimeException("该用户已经存在!");
        }
        entity.setCreateId(createId);
        entity.setCreateTime(LocalDateTime.now());
        if (StrUtils.isBlank(entity.getSalt())) {
            entity.setSalt(SecurityUtils.getMd5(StrUtils.getUUID()));
        }
        entity.setLastLoginIp("");
        entity.setLastLoginTime(0L);
        entity.setPassword(SecurityUtils.getMd5(entity.getSalt() + entity.getLastLoginTime() + entity.getPassword()));
        if (!save(entity)) {
            throw new RuntimeException("保存管理员失败!");
        }
        Collection<Long> roleIds = entity.getRoleIds();
        Long id = entity.getId();
        List<AdminRoleItemEntity> itemList = new ArrayList<>(roleIds.size());
        roleIds.forEach(roleId -> {
            AdminRoleItemEntity adminRoleItemEntity = new AdminRoleItemEntity();
            adminRoleItemEntity.setAdminId(id);
            adminRoleItemEntity.setRoleId(roleId);
            itemList.add(adminRoleItemEntity);
        });
        if (!roleItemService.saveBatch(itemList)) {
            throw new RuntimeException("保存角色信息失败!");
        }
    }

    @Override
    public void updateAdminAndRole(AdminEntity entity, Long createId) {
        Long id = entity.getId();
        if (StrUtils.isNotBlank(entity.getPassword())) {
            if (StrUtils.isBlank(entity.getSalt())) {
                entity.setSalt(SecurityUtils.getMd5(StrUtils.getUUID()));
            }
            AdminEntity adminEntity = this.selectOne(id);
            entity.setPassword(SecurityUtils.getMd5(entity.getSalt() + adminEntity.getLastLoginTime() + entity.getPassword()));
        }
        if (!updateById(entity)) {
            throw new RuntimeException("修改管理员失败!");
        }
        List<AdminRoleItemEntity> sourceList = roleItemService.findListByFieldValue(AdminRoleItemEntity::getAdminId, id);
        Collection<Long> roleIds = entity.getRoleIds();
        List<AdminRoleItemEntity> itemList = new ArrayList<>(roleIds.size());
        roleIds.forEach(roleId -> {
            boolean flag = sourceList.removeIf(itemEntity -> itemEntity.getId().equals(roleId));
            if (!flag) {
                AdminRoleItemEntity adminRoleItemEntity = new AdminRoleItemEntity();
                adminRoleItemEntity.setAdminId(id);
                adminRoleItemEntity.setRoleId(roleId);
                itemList.add(adminRoleItemEntity);
            }
        });
        if (!roleItemService.saveBatch(itemList)) {
            throw new RuntimeException("保存角色信息失败!");
        }
        if (sourceList.size() > 0) {
            List<Long> ids = sourceList.stream().map(AdminRoleItemEntity::getId).collect(Collectors.toList());
            if (!roleItemService.removeByIds(ids)) {
                throw new RuntimeException("保存角色信息失败!");
            }
        }
    }

    private void saveRoles(Long id, Collection<Long> roleIds) {
        if (!CollectionUtils.isEmpty(roleIds)) {
            LinkedHashSet<AdminRoleItemEntity> list = new LinkedHashSet<>();
            roleIds.forEach(roleId -> {
                AdminRoleItemEntity item = new AdminRoleItemEntity();
                item.setAdminId(id);
                item.setRoleId(roleId);
                list.add(item);
            });
            if (!roleItemService.saveBatch(list)) {
                throw new RuntimeException("保存角色信息失败!");
            }
        }
    }

    @Override
    public void updateAdmin(Long id, AdminEntity entity, Long updateId) {
        entity.setId(null);
        if (!update(entity, "id = {0}", id)) {
            throw new RuntimeException("修改管理员失败!");
        }
        roleItemService.delete("admin_id = {0}", id);
        Collection<Long> roleIds = entity.getRoleIds();
        saveRoles(id, roleIds);
    }

    @Override
    public Boolean deleteAdmin(Long id) {
        roleItemService.delete("admin_id = {0}", id);
        return removeById(id);
    }

    @Override
    public List<AdminEntity> findByIds(List<Long> adminIds) {
        QueryWrapper<AdminEntity> wrapper = new QueryWrapper<>();
        wrapper.in("id", adminIds);
        return this.list(wrapper);
    }
}
